﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using Point = System.Windows.Point;
using Size = System.Windows.Size;

namespace Haidou.Wpf.UI.Controls
{
	/// <summary>
	/// 径向布局面板，可均匀或自定义角度放置子元素。
	/// 支持：Radius / Center / StartAngle / SweepAngle / (子元素)Angle 附加属性。
	/// 如果子元素设置 <code>RadialPanel.Angle</code> (度)，则按该角度放置；否则在 SweepAngle 范围内均分。
	/// </summary>
	public class RadialPanel : System.Windows.Controls.Panel
	{
		// Radius
		public static readonly DependencyProperty RadiusProperty =
			DependencyProperty.Register(
				name: nameof(Radius),
				propertyType: typeof(double),
				ownerType: typeof(RadialPanel),
				new FrameworkPropertyMetadata(120d, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
		public double Radius { get => (double)GetValue(RadiusProperty); set => SetValue(RadiusProperty, value); }

		// Center
		public static readonly DependencyProperty CenterProperty =
			DependencyProperty.Register(
				name: nameof(Center),
				propertyType: typeof(Point),
				ownerType: typeof(RadialPanel),
				new FrameworkPropertyMetadata(new Point(50, 50), FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
		public Point Center { get => (Point)GetValue(CenterProperty); set => SetValue(CenterProperty, value); }

		// StartAngle (度) 默认从 -90 顶部开始
		public static readonly DependencyProperty StartAngleProperty =
			DependencyProperty.Register(
				name: nameof(StartAngle),
				propertyType: typeof(double),
				ownerType: typeof(RadialPanel),
				new FrameworkPropertyMetadata(-90d, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
		public double StartAngle { get => (double)GetValue(StartAngleProperty); set => SetValue(StartAngleProperty, value); }

		// SweepAngle 分布总角度，默认 360
		public static readonly DependencyProperty SweepAngleProperty =
			DependencyProperty.Register(
				name: nameof(SweepAngle),
				propertyType: typeof(double),
				ownerType: typeof(RadialPanel),
				new FrameworkPropertyMetadata(360d, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
		public double SweepAngle { get => (double)GetValue(SweepAngleProperty); set => SetValue(SweepAngleProperty, value); }

		// 子元素附加属性: Angle (若未设或为 NaN 则均分)
		public static readonly DependencyProperty AngleProperty =
			DependencyProperty.RegisterAttached(
				"Angle",
				typeof(double),
				typeof(RadialPanel),
				new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange));
		public static void SetAngle(UIElement element, double value) => element.SetValue(AngleProperty, value);
		public static double GetAngle(UIElement element) => (double)element.GetValue(AngleProperty);

		protected override Size MeasureOverride(Size availableSize)
		{
			// 目标布局区域（限制最小直径以放得下所有子项）
			double diameter = Radius * 2 + 2; // 少量边距
			var panelSize = new Size(
				width: double.IsInfinity(availableSize.Width) ? diameter : Math.Max(diameter, availableSize.Width),
				height: double.IsInfinity(availableSize.Height) ? diameter : Math.Max(diameter, availableSize.Height));

			// 子元素测量——给予足够空间，不依赖父级大小，避免频繁触发布局动画创建
			//foreach (UIElement child in InternalChildren)
			//{
			//	child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
			//}
			return panelSize;
		}

		protected override Size ArrangeOverride(Size finalSize)
		{
			int count = InternalChildren.Count;
			if (count == 0) return finalSize;

			// 收集显式角度
			var explicitAngles = new Dictionary<UIElement, double>();
			var autoList = new List<UIElement>();
			foreach (UIElement child in InternalChildren)
			{
				double a = GetAngle(child);
				if (double.IsNaN(a)) autoList.Add(child); else explicitAngles[child] = a;
			}

			// 为自动项分配均匀角度 (避免与显式角度冲突由用户自行控制)
			if (autoList.Count > 0)
			{
				double step = SweepAngle / autoList.Count;
				for (int i = 0; i < autoList.Count; i++)
				{
					explicitAngles[autoList[i]] = StartAngle + i * step;
				}
			}

			foreach (var kv in explicitAngles)
			{
				UIElement child = kv.Key;
				double angleDeg = kv.Value;
				double angleRad = angleDeg * Math.PI / 180.0;
				double x = Center.X + Math.Cos(angleRad) * Radius - child.DesiredSize.Width / 2;
				double y = Center.Y + Math.Sin(angleRad) * Radius - child.DesiredSize.Height / 2;
				child.Arrange(new Rect(new Point(x, y), child.DesiredSize));
			}
			return finalSize;
		}
	}
}
